﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.ComponentModel;
using System.Collections.Generic;
using System.Windows.Data;
using System.IO;
using System.Linq;

using Cinch;
using MEFedMVVM.ViewModelLocator;
using MEFedMVVM.Services.Contracts;
using MEFedMVVM.Common;
using System.Windows.Threading;
using System.Threading;
using System.Configuration;


namespace Anata.Client
{
    /// <summary>
    /// This is a workspace type ViewModel, which is created by some code in the <c>MainWindowViewModel</c>
    /// and the DataTemplate in the <c>MainWindow.xaml</c>
    /// 
    /// This is the main ViewModel of the demo app, and this ViewModel makes use
    /// of pretty much all the Cinch services available.
    /// 
    /// This ViewModel is also able to operate in design mode by using the
    /// <c>IImageProvider</c> data service, which can either be a runtime service or a design time service
    /// 
    /// This ViewModel is also expecting some contextual data from the <c>IViewAwareStatus</c> service
    /// (as we are using a View 1st type of development in CinchV2). This contextual data is the
    /// image path that the <c>IImageProvider</c> data service uses to fetch images.
    /// 
    /// As such this ViewModel expects the <c>IViewAwareStatus</c> service which allows the ViewModel
    /// to examine this contextual view data
    /// 
    /// Anyway in this ViewModel you will find a demo of most of the services Cinch has to offer
    /// </summary>
    [ExportViewModel("KaryawanListViewModel")]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class KaryawanListViewModel : ViewModelBase
    {
        #region Data
        //private ViewMode currentViewMode = ViewMode.AddMode;

        #region Data.Primitives
        private String filterKeyword = "";

        private bool isAllLoaded = false;
        private int pageLoaded = 0;
        private DispatcherTimer filterTimer;
        #endregion

        //private IEnumerable<DataWrapperBase> cachedListOfDataWrappers;
        
        #region Data.Rules
        #endregion
        
        #region Data.VMs
        private DispatcherNotifiedObservableCollection<KaryawanThumbnailViewModel> karyawans;
        private ICollectionView karyawansCV;
        #endregion

        #region Data.Services
        private IViewAwareStatus viewAwareStatusService;
        private IMessageBoxService messageBoxService;
        private IUIVisualizerService uiVisualizerService;
        private IKaryawanProvider karyawanProvider;
        private IReferenceProvider referenceProvider;
        #endregion

        #endregion

        #region Constructor
        [ImportingConstructor]
        public KaryawanListViewModel(
            IMessageBoxService messageBoxService,
            IUIVisualizerService uiVisualizerService,
            IViewAwareStatus viewAwareStatusService,
            IKaryawanProvider karyawanProvider,
            IReferenceProvider referenceProvider)
        {
            #region Constructor.SetupServices
            this.messageBoxService = messageBoxService;
            this.uiVisualizerService = uiVisualizerService;
            this.viewAwareStatusService = viewAwareStatusService;
            this.viewAwareStatusService.ViewLoaded += ViewAwareStatusService_ViewLoaded;
            this.karyawanProvider = karyawanProvider;
            this.referenceProvider = referenceProvider;
            #endregion

            #region Constructor.SetupCommands
            KaryawanNewCommand = new SimpleCommand<Object, Object>(CanExecuteKaryawanNewCommand, ExecuteKaryawanNewCommand);
            KaryawanRefreshCommand = new SimpleCommand<Object, Object>(CanExecuteKaryawanRefreshCommand, ExecuteKaryawanRefreshCommand);
            KaryawanSelectCommand = new SimpleCommand<Object, Object>(CanExecuteKaryawanSelectCommand, ExecuteKaryawanSelectCommand);
            KaryawanFilterKeyUpCommand = new SimpleCommand<Object, Object>(CanExecuteKaryawanFilterKeyUpCommand, ExecuteKaryawanFilterKeyUpCommand);
            #endregion

            #region Constructor.SetupDataWrappers
            #endregion

            #region Constructor.SetupValidationRules
            #endregion

            #region Constructor.SetupVMs
            Karyawans = new DispatcherNotifiedObservableCollection<KaryawanThumbnailViewModel>();
            KaryawansCV = CollectionViewSource.GetDefaultView(karyawans);
            #endregion

            Mediator.Instance.Register(this);

            #region Constructor.Filter
            filterTimer = new DispatcherTimer();
            filterTimer.Interval = TimeSpan.FromMilliseconds(
                Int32.Parse(ConfigurationManager.AppSettings["FilterResponsiveness"].ToString()));
            filterTimer.Tick += new EventHandler(LazyFilterCallback);
            #endregion
        }
        #endregion

        #region Public Properties

        #region Public.Commands
        public SimpleCommand<Object, Object> KaryawanNewCommand { get; private set; }
        public SimpleCommand<Object, Object> KaryawanRefreshCommand { get; private set; }
        public SimpleCommand<Object, Object> KaryawanFilterKeyUpCommand { get; private set; }
        public SimpleCommand<Object, Object> KaryawanSelectCommand { get; private set; }
        #endregion

        #region Public.ViewMode
        #endregion

        #region Public.Data
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs karyawansChangeArgs =
            ObservableHelper.CreateArgs<KaryawanListViewModel>(x => x.Karyawans);
        public DispatcherNotifiedObservableCollection<KaryawanThumbnailViewModel> Karyawans
        {
            get { return karyawans; }
            set
            {
                karyawans = value;
                NotifyPropertyChanged(karyawansChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs karyawansCVChangeArgs =
            ObservableHelper.CreateArgs<KaryawanListViewModel>(x => x.KaryawansCV);
        public ICollectionView KaryawansCV
        {
            get { return karyawansCV; }
            set
            {
                karyawansCV = value;
                NotifyPropertyChanged(karyawansCVChangeArgs);
            }
        }



        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs filterKeywordChangeArgs =
            ObservableHelper.CreateArgs<KaryawanListViewModel>(x => x.FilterKeyword);
        public String FilterKeyword
        {
            get { return filterKeyword; }
            set
            {
                filterKeyword = value;
                NotifyPropertyChanged(filterKeywordChangeArgs);
                LazyFilter();
            }
        }
        #endregion

        #region Public.CachedCollection
        #endregion

        #endregion

        #region Command Handlers
        /// <summary>
        /// </summary>
        private bool CanExecuteKaryawanNewCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteKaryawanNewCommand(Object args)
        {
            KaryawanThumbnailViewModel ttvm = new KaryawanThumbnailViewModel();
            karyawans.Add(ttvm);
            Mediator.Instance.NotifyColleagues<KaryawanThumbnailViewModel>(
                "TryActivateKaryawanDetail", ttvm);
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteKaryawanRefreshCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteKaryawanRefreshCommand(Object args)
        {
            pageLoaded = 0;
            isAllLoaded = false;
            karyawans.Clear();
            LoadKaryawans();
        }

        /// <summary>
        /// </summary>
        private bool CanExecuteKaryawanFilterKeyUpCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteKaryawanFilterKeyUpCommand(Object args)
        {
            //EventToCommandArgs eventArgs = args as EventToCommandArgs;
            //TextBox tb = eventArgs.Sender as TextBox;
            //LazyFilter(tb.Text);
            //NotifyPropertyChanged(filterKeywordChangeArgs);
            LazyFilter();
        }
        
        /// <summary>
        /// </summary>
        private bool CanExecuteKaryawanSelectCommand(Object args)
        {
            return true;
        }
        /// <summary>
        /// </summary>
        private void ExecuteKaryawanSelectCommand(Object args)
        {
            KaryawanThumbnailViewModel ttvm = (KaryawanThumbnailViewModel)KaryawansCV.CurrentItem;
            if (ttvm != null)
            {
                Mediator.Instance.NotifyColleagues<KaryawanThumbnailViewModel>(
                    "TryActivateKaryawanDetail", ttvm);
            }
        }

        #endregion

        #region Mediator Message Sinks
        [MediatorMessageSink("TryHighlightKaryawanThumbnail")]
        private void TryHighlightKaryawanThumbnail(KaryawanThumbnailViewModel ktvm)
        {
            if (this.karyawansCV.Contains(ktvm) && !ktvm.Equals(this.karyawansCV.CurrentItem))
            {
                this.karyawansCV.MoveCurrentTo(ktvm);
                Console.WriteLine("posisi #" + KaryawansCV.CurrentPosition + ": " + KaryawansCV.CurrentItem);
            }
        }

        [MediatorMessageSink("TryRefreshKaryawanThumbnail")]
        private void TryRefreshKaryawanThumbnail(int idKaryawan)
        {
            try
            {
                KaryawanThumbnailViewModel ktvm = karyawans.First(k => k.IdKaryawan == idKaryawan);
                if (!ktvm.IsBusy)
                {
                    ktvm.IsBusy = true;
                    Dispatcher.CurrentDispatcher.InvokeIfRequired(() =>
                    {
                        karyawanProvider.LazyLoadJadwalKaryawan(ktvm, PostLoadKaryawan);
                    }, DispatcherPriority.Background);
                }
            }
            catch (Exception) { }
        }

        [MediatorMessageSink("TryUpgradeTransaksiLayananThumbnail")]
        private void TryUpgradeTransaksiLayananThumbnail(KaryawanThumbnailViewModel ktvm)
        {
        }

        [MediatorMessageSink("TryDowngradeTransaksiLayananThumbnail")]
        private void TryDowngradeTransaksiLayananThumbnail(KaryawanThumbnailViewModel ttvm)
        {
        }
        #endregion

        #region PrivateMethods
        #region PrivateMethods.ViewLoaded
        private void ViewAwareStatusService_ViewLoaded()
        {
            LoadKaryawans();
        }
        #endregion

        #region PrivateMethods.Filter
        private void LazyFilter()
        {
            filterTimer.Stop();
            filterTimer.Start();
        }
        private void LazyFilterCallback(object sender, EventArgs e)
        {
            Console.WriteLine("stopped typing, filtering with keyword: " + filterKeyword);
            filterTimer.Stop();
            if (filterKeyword != "")
            {
                karyawansCV.Filter = new Predicate<object>(LazyFilterPredicate);
            }
            else
            {
                karyawansCV.Filter = null;
            }
        }
        private bool LazyFilterPredicate(object row)
        {
            KaryawanThumbnailViewModel ktvm = row as KaryawanThumbnailViewModel;
            return (ktvm.Nama.ToLower().Contains(filterKeyword.ToLower()));
        }
        #endregion

        #region PrivateMethods.Loader
        /// <summary>
        /// loader
        /// </summary>
        private void LoadKaryawans()
        {
            karyawanProvider.LazyFetchJadwalKaryawans(pageLoaded, PostLoadKaryawans);
        }
        #endregion

        #region PrivateMethods.PostLoader
        private void PostLoadKaryawan(KaryawanThumbnailViewModel ktvm)
        {
            if (ktvm != null)
            {
                ktvm.IsBusy = false;
            }
        }
        /// <summary>
        /// post loader
        /// </summary>
        private void PostLoadKaryawans(List<KaryawanThumbnailViewModel> dbKaryawans)
        {
            //rekursif sampai semua diload
            int pageSize = Int32.Parse(ConfigurationManager.AppSettings["LazyLoadPageSize"].ToString());
            DispatcherNotifiedObservableCollection<KaryawanThumbnailViewModel> ttvms = 
                new DispatcherNotifiedObservableCollection<KaryawanThumbnailViewModel>(dbKaryawans);
            foreach (KaryawanThumbnailViewModel item in dbKaryawans)
            {
                karyawans.Add(item);
                Console.WriteLine("Nambah Karyawan: " + item.Nama + " : " + item);
            }

            if (dbKaryawans.Count != pageSize)
            {
                //basis
                //sudah habis, done loading
                isAllLoaded = true;
            }
            else
            {
                //rekurens
                ++pageLoaded;
                LoadKaryawans();
            }
        }
        #endregion

        #endregion
    }

}
